#include "wifi.h"
#include "http_server.h"
#include "api_map.h"

void wifi_status_notice_cb(uint8_t status, void *value)
{
    if (status == WIFI_STATUS_SCAN_DONE)
    {
        uint16_t len = 0;
        char *str = (char *)wifi_stack->buffer;
        len += sprintf(&str[len], "{");
        len += sprintf(&str[len], "\"api\":\"wifi_scan\",");
        len += sprintf(&str[len], "\"data\":[");
        for (int i = 0; i < wifi_stack->scan_ap_count; i++)
        {
            len += sprintf(&str[len], "{");
            len += sprintf(&str[len], "\"ssid\":\"%s\",", wifi_stack->scan_ap_infos[i].ssid);
            len += sprintf(&str[len], "\"rssi\":%d,", wifi_stack->scan_ap_infos[i].rssi);
            len += sprintf(&str[len], "\"mac\":[%d,%d,%d,%d,%d,%d],", wifi_stack->scan_ap_infos[i].bssid[0], wifi_stack->scan_ap_infos[i].bssid[1], wifi_stack->scan_ap_infos[i].bssid[2], wifi_stack->scan_ap_infos[i].bssid[3], wifi_stack->scan_ap_infos[i].bssid[4], wifi_stack->scan_ap_infos[i].bssid[5]);
            len += sprintf(&str[len], "\"channel\":%d,", wifi_stack->scan_ap_infos[i].primary);
            len += sprintf(&str[len], "\"auth\":%s", wifi_stack->scan_ap_infos[i].authmode ? "true" : "false");
            len += sprintf(&str[len], "},");
        }
        len -= 1;
        len += sprintf(&str[len], "]");
        len += sprintf(&str[len], "}");
        ws_send_msg(wifi_stack->buffer, len);
    }
    else if (status == WIFI_STATUS_GOT_IP)
    {
        uint16_t len = 0;
        char *str = (char *)wifi_stack->buffer;
        len += sprintf(&str[len], "{");
        len += sprintf(&str[len], "\"api\":\"wifi_connect\",");
        len += sprintf(&str[len], "\"data\":0");
        len += sprintf(&str[len], "}");
        ws_send_msg(wifi_stack->buffer, len);
    }
}

static void get_config_wifi(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    uint16_t len = 0;
    char *str = (char *)server->data;
    len += sprintf(&str[len], "{");
    len += sprintf(&str[len], "\"api\":\"get_config_wifi\",");
    len += sprintf(&str[len], "\"data\":{");
    len += sprintf(&str[len], "\"moode\":%d,", wifi_stack->storage.mode);
    len += sprintf(&str[len], "\"sta\":{");
    len += sprintf(&str[len], "\"on\":%s,", wifi_stack->mode & WIFI_MODE_STA ? "true" : "false");
    uint8_t mac[6];
    uint32_t ip = wifi_get_localIP();
    if (ip)
    {
        wifi_ap_record_t ap_info = {0};
        esp_wifi_sta_get_ap_info(&ap_info);
        len += sprintf(&str[len], "\"signal\":%d,", ap_info.rssi);
        len += sprintf(&str[len], "\"ssid\":\"%s\",", wifi_get_sta_ssid());
#define ip2str(ip) ((uint8_t *)ip)[0], ((uint8_t *)ip)[1], ((uint8_t *)ip)[2], ((uint8_t *)ip)[3]
        esp_wifi_get_mac(WIFI_IF_STA, mac);
        len += sprintf(&str[len], "\"mac\":\"" MACSTR "\",", MAC2STR(mac));
        len += sprintf(&str[len], "\"ip\":\"%u.%u.%u.%u\",", ip2str(&ip));
        ip = wifi_get_subnetMask();
        len += sprintf(&str[len], "\"mask\":\"%u.%u.%u.%u\",", ip2str(&ip));
        ip = wifi_get_gateway();
        len += sprintf(&str[len], "\"gateway\":\"%u.%u.%u.%u\",", ip2str(&ip));
        len += sprintf(&str[len], "\"dns\":\"%u.%u.%u.%u\",", ip2str(&ip));
    }
    uint8_t mode = 0;
    len += sprintf(&str[len], "\"ip_mode\":%d,", mode);
    // if (mode)
    {
        len += sprintf(&str[len], "\"ip_config\":{");
        len += sprintf(&str[len], "\"ip\":\"%u.%u.%u.%u\",", ip2str(&wifi_stack->storage.sta_ip_config.ip));
        len += sprintf(&str[len], "\"mask\":\"%u.%u.%u.%u\",", ip2str(&wifi_stack->storage.sta_ip_config.mask));
        len += sprintf(&str[len], "\"gateway\":\"%u.%u.%u.%u\"", ip2str(&wifi_stack->storage.sta_ip_config.gateway));
        len += sprintf(&str[len], "},");
    }
    mode = 0;
    len += sprintf(&str[len], "\"dns_mode\":%d,", mode);
    // if (mode)
    {
        len += sprintf(&str[len], "\"dns_config\":\"%u.%u.%u.%u\"", ip2str(&ip));
    }
    len += sprintf(&str[len], "},");
    len += sprintf(&str[len], "\"ap\":{");
    len += sprintf(&str[len], "\"on\":%s,", (wifi_stack->mode == WIFI_MODE_AP || wifi_stack->mode == WIFI_MODE_APSTA) ? "true" : "false");
    len += sprintf(&str[len], "\"ssid\":\"%s\",", wifi_get_ap_ssid());
    len += sprintf(&str[len], "\"password\":\"%s\",", wifi_get_ap_passwd());
    esp_wifi_get_mac(WIFI_IF_AP, mac);
    len += sprintf(&str[len], "\"mac\":\"" MACSTR "\",", MAC2STR(mac));
    len += sprintf(&str[len], "\"ip\":\"%u.%u.%u.%u\",", ip2str(&wifi_stack->storage.ap_ip_config.ip));
    len += sprintf(&str[len], "\"mask\":\"%u.%u.%u.%u\",", ip2str(&wifi_stack->storage.ap_ip_config.mask));
    len += sprintf(&str[len], "\"gateway\":\"%u.%u.%u.%u\"", ip2str(&wifi_stack->storage.ap_ip_config.gateway));

    len += sprintf(&str[len], "}");
    len += sprintf(&str[len], "}");
    len += sprintf(&str[len], "}");
    frame->payload = server->data;
    frame->len = len;
}

static void wifi_scan(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    wifi_stack->user_call_scan = 1;
    wifi_start_sta();
    wifi_scan_start(0);
}

static void wifi_connect(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    if (!cJSON_HasObjectItem(data, "ssid"))
        goto wifi_connect_failed;
    char *ssid = cJSON_GetObjectItem(data, "ssid")->valuestring;
    char *password = NULL;
    if (cJSON_HasObjectItem(data, "password"))
        password = cJSON_GetObjectItem(data, "password")->valuestring;
    wifi_start_sta();
    wifi_set_sta(ssid, password);
    return;
wifi_connect_failed:
    ws_reply_status(server, frame, "wifi_connect", -1);
}

static void wifi_config_ap(http_server_t server, httpd_ws_frame_t *frame, void *data)
{
    if (!cJSON_HasObjectItem(data, "on"))
        goto wifi_config_ap_failed;
    if (cJSON_GetObjectItem(data, "on")->type & cJSON_True)
    {
        if (!cJSON_HasObjectItem(data, "ssid"))
            goto wifi_config_ap_failed;
        char *ssid = cJSON_GetObjectItem(data, "ssid")->valuestring;
        char *password = NULL;
        if (cJSON_HasObjectItem(data, "password"))
            password = cJSON_GetObjectItem(data, "password")->valuestring;
        wifi_start_ap();
        wifi_set_ap(ssid, password);
    }
    else
        wifi_stop_ap();
    ws_reply_status(server, frame, "wifi_config_ap", 0);
    return;
wifi_config_ap_failed:
    ws_reply_status(server, frame, "wifi_config_ap", -1);
}

static void wifi_api_init(void)
{
    ADD_API_ITEM(get_config_wifi);
    ADD_API_ITEM(wifi_scan);
    ADD_API_ITEM(wifi_connect);
    ADD_API_ITEM(wifi_config_ap);
}
ADD_API(wifi_api_init)
